<template>
  <div class="chart">
    <div
      class="chart-content"
      ref="chartRef"
      :style="{
        width: width + 'px',
        height: chartHeight + 'px',
        transform: `scale(${1 / slideScale})`,
        color: '#000',
        filter: filter
      }"
    ></div>
    <!-- <div class="legends" :style="{ transform: `scale(${1 / slideScale})` }" v-if="legend">
      <div class="legend" v-for="(legend, index) in legends" :key="index" :style="{ color: gridColor }">
        <div class="block" :style="{ backgroundColor: themeColors[index] }"></div>
        {{ legend }}
      </div>
    </div> -->
  </div>
</template>

<script lang="ts">
import {
  computed,
  defineComponent,
  inject,
  nextTick,
  onMounted,
  PropType,
  ref,
  Ref,
  watch,
} from "vue";
import { upperFirst } from "lodash";
import tinycolor from "tinycolor2";
import Chartist, {
  IChartistLineChart,
  IChartistBarChart,
  IChartistPieChart,
  ILineChartOptions,
  IBarChartOptions,
  IPieChartOptions,
} from "chartist";
import { ChartData, ChartType, antvChartData } from "@/types/slides";
import { useMainStore, useSlidesStore } from "@/store";
import { storeToRefs } from "pinia";
import useHistorySnapshot from "@/hooks/useHistorySnapshot";

import "chartist/dist/scss/chartist.scss";
// import DataSet from '@antv/data-set'
import { Chart, registerShape } from "@antv/g2";
import { ChartStock } from "@icon-park/vue-next";
import { useScreenStore } from "@/store/screen";
import useFilter from '../ImageElement/useFilter'

export default defineComponent({
  name: "chart",
  props: {
    width: {
      type: Number,
      required: true,
    },
    height: {
      type: Number,
      required: true,
    },
    type: {
      type: String as PropType<ChartType>,
      required: true,
    },
    data: {
      type: Object as PropType<antvChartData>,
      required: true,
    },
    options: {
      type: Object as PropType<
        ILineChartOptions & IBarChartOptions & IPieChartOptions
      >,
    },
    themeColor: {
      type: Array as PropType<string[]>,
      required: true,
    },
    // legends: {
    //   type: Array as PropType<string[]>,
    //   required: true,
    // },
    gridColor: {
      type: String,
    },
    legend: {
      type: String as PropType<"" | "top" | "bottom">,
    },
    id: {
      type: String,
    },
    attribute: {
      type: Object
    },
    filters: {
      type: Object
    }
  },
  setup(props) {
    const slidesStore = useSlidesStore();
    const screenStore = useScreenStore();
    const chartRef = ref<HTMLElement>();
    const slideScale: Ref<number> = inject("slideScale") || ref(1);
    const mainStore = useMainStore();
    const { handleElement, handleElementId } = storeToRefs(mainStore);
    const { slides } = storeToRefs(slidesStore)
    const { addHistorySnapshot } = useHistorySnapshot();
    const legend = ref();
    // let chart: IChartistLineChart | IChartistBarChart | IChartistPieChart | undefined
    let charts: any;
    const filters = computed(() => props.filters)
    const { filter } = useFilter(filters)
    const chartHeight = computed(() => {
      // if (props.legend) return props.height - 20
      return props.height;
    });

    // const getDataAndOptions = () => {
    //   const propsOptopns = props.options || {}
    //   const options = {
    //     ...propsOptopns,
    //     width: props.width * slideScale.value,
    //     height: chartHeight.value * slideScale.value,
    //   }
    //   const data = props.type === 'pie' ? { ...props.data, series: props.data.series[0] } : props.data
    //   return { data, options }
    // }

    watch(
      () => chartHeight.value,
      (val) => {
        charts.changeSize(
          props.width * slideScale.value,
          chartHeight.value * slideScale.value
        );
      }
    );
    // const data = [
    //   { type: '一线城市', value: 0.19 },
    //   { type: '二线城市', value: 0.21 },
    //   { type: '三线城市', value: 0.27 },
    //   { type: '四线及以下', value: 0.33 },
    // ];
    watch(
      () => slideScale.value,
      (val) => {
        // if(val!=0) renderChart()
      }
    );
    watch(
      () => props.attribute,
      (val) => {
        if(val) {
          nextTick(()=> {
            charts.padding = [val.grid.top, val.grid.right, val.grid.bottom, val.grid.left]
            charts.render();
          })
        }
      },
      {
        deep: true,
        immediate: true
      }
    )
    watch(
      () => props.legend,
      (val) => {
        console.log(val,'val')
        nextTick(() => {
          if (val) {
            charts.legend({
              position: val,
            });
          } else if (val == "") {
            charts.legend(false);
          }
          charts.render();
        })
      },
      {
        immediate: true
      }
    );

    const renderChart = () => {
      // if (!chartRef.value) return

      const type = upperFirst(props.type);
      // const { data, options } = getDataAndOptions()
      // chart = new Chartist[type](chartRef.value, data, options)
      let dom = chartRef.value as HTMLElement;
      let s = props.data.type.s;
      let x = props.data.type.x;
      let y = props.data.type.y;
      let position = props.data.type.position;
      let adjust = props.data.type.adjust;
      let transpose = props.data.type.transpose;
      let xLine = props.data.type.xLine;
      let diff = props.data.type.diff;
      let bubble = props.data.type.bubble;
      let square = props.data.type.square;

      charts = new Chart({
        container: dom,
        autoFit: false,
        height: chartHeight.value * slideScale.value,
        width: props.width * slideScale.value,
        padding: [20, 10, 30, 40],
      });
      if (props.legend) {
        charts.legend({
          position: props.legend,
        });
      } else {
        charts.legend(false);
      }

      if (props.data) {
        charts.data(props.data.data);
      }

      charts.scale(y, {
        alias: "",
      });

      charts.axis(x, {
        tickLine: false,
      });

      if (xLine) {
        charts.axis(y, {
          tickCount: 6,
          grid: {
            line: {
              style: {
                stroke: "#d9d9d9",
                lineWidth: 1,
                lineDash: [2, 2],
              },
            },
          },
        });
      } else {
        charts.axis(y, false);
      }

      charts.theme({
        styleSheet: {
          paletteQualitative10: [
            "l(90) 0:#43E8F3 0.8:#43E8F3 1:#041011",
            "l(90) 0:#3B99FB 0.8:#3B99FB 1:#091725",
            "#2498D1",
            "#BBBDE6",
            "#4045B2",
            "#21A97A",
            "#FF745A",
            "#007E99",
            "#FFA8A8",
            "#2391FF",
          ],
        },
      });
      charts.tooltip({
        showMarkers: false,
      });

      if (adjust) {
        charts
          .interval()
          .position(position)
          .color(s)
          .size(11)
          .adjust([
            {
              type: "dodge",
              marginRatio: 0,
            },
          ]);
      } else if (square) {
        // registerShape('interval', 'triangle', {
        //   // 1. 定义关键点
        //   getPoints(cfg) {
        //     const xcfg: any = cfg.x;
        //     const ycfg = cfg.y;
        //     const y0 = cfg.y0;
        //     const width: any = cfg.size;
        //     return [
        //       { x: xcfg - width / 2, y: y0 },
        //       { x: xcfg, y: ycfg },
        //       { x: xcfg + width / 2, y: y0 },
        //     ];
        //   },
        //   // 2. 绘制
        //   draw(cfg, group) {
        //     const points = this.parsePoints(cfg.points); // 将0-1空间的坐标转换为画布坐标
        //     console.log(cfg);
        //     const polygon = group.addShape('path', {
        //       attrs: {
        //         path: [
        //           ['M', points[0].x, points[0].y],
        //           ['L', points[1].x, points[1].y],
        //           ['L', points[2].x, points[2].y],
        //         ],
        //         ...cfg.defaultStyle,
        //       },
        //     });
        //     return polygon;
        //   },
        // });

        charts
          .interval()
          .position(position)
          .size(10)
          .style({ radius: 20 })
          // .color('l(90) 0:#399EFE 1:#06F6F0')
          .color(s);
      } else if (!diff && position != undefined) {
        charts
          .interval()
          .position(position)
          // .color('l(90) 0:#3B99FB 1:#091725')
          .color(s)
          .size(10);
      }

      if (transpose) {
        charts.coordinate().transpose();
      }

      //对比图
      if (diff) {
        charts.facet("mirror", {
          fields: [s],
          transpose: true,
          showTitle: false,
          eachView: (view: any, facet: any) => {
            const facetIndex = facet.columnIndex;
            view.axis(x, {
              position: "top",
              label: {
                style: {
                  fill: "#aaaaaa",
                  fontSize: 12,
                },
              },
              tickLine: {
                alignTick: false,
                length: 0,
              },
              line: null,
            });
            const color =
              facetIndex === 0
                ? "l(180) 0:#3ca0fe 1:#43e7f3"
                : "l(0) 0:#39e9ab 1:#42e8f1";
            view
              .interval()
              .position(position)
              .color(color)
              .size(11)
              .style({ radius: 20 });
          },
        });
      }

      //气泡图
      if (bubble) {
        charts
          .point()
          .position(position)
          .color("#f1f1f1")
          .size(10)
          .shape("circle")
          // .tooltip('x*y*z')
          .style({
            lineWidth: 1,
            stroke: "#f1f1f1",
            fillOpacity: 1,
            padding: 10,
          });
      }

      if (square) {
        // charts
        //   .point()
        //   .position()
        //   .color('#3B99FB')
        //   .size(5)
        //   .shape('triangle-down')
        //   .style({
        //     lineWidth: 1,
        //     stroke: '#3B99FB',
        //     fillOpacity: 1,
        //   });
      }

      charts.interaction("element-active");
      charts.render();
    };
    const { handleElementOtherIdList } = storeToRefs(useMainStore());
    const updateChart = (val: any) => {
      //图表协同
      handleElementOtherIdList.value.map((item: any) => {
        item.handleElementId == props.id ? charts.changeData(val.data) : ''
      })

      if (props.id != handleElement.value?.id) {
        return;
      }
      // const { data, options } = getDataAndOptions()

      if (handleElement.value?.type == "chart" && handleElement.value?.data) {
        let s = handleElement.value?.data.type.s;
        let x = handleElement.value?.data.type.x;
        let y = handleElement.value?.data.type.y;
        let data = handleElement.value?.data.data;
        charts.changeData(data); // 更新数据源
        // do something
        // charts.render(); // 更新图表
        // renderChart()
      }
      // chart.update(data, options)
    };

    // watch(
    //   [
    //     // () => props.width,
    //     // () => props.height,
    //     () => props.data,
    //     // slideScale,
    //   ],
    //   updateChart,
    //   { deep: true }
    // );

    watch(
      () => props.data,
      (val) => {
        updateChart(val);
      },
      { deep: true }
    );

    onMounted(() => {
      if (screenStore.screening) {
        nextTick(() => {
          renderChart();
        });
      } else {
        renderChart();
      }
    });

    const themeColors = computed(() => {
      let colors: string[] = [];
      if (props.themeColor.length >= 10) colors = props.themeColor;
      else if (props.themeColor.length === 1)
        colors = tinycolor(props.themeColor[0])
          .analogous(10)
          .map((color) => color.toHexString());
      else {
        const len = props.themeColor.length;
        const supplement = tinycolor(props.themeColor[len - 1])
          .analogous(10 + 1 - len)
          .map((color) => color.toHexString());
        colors = [...props.themeColor.slice(0, len - 1), ...supplement];
      }

      return colors;
    });

    // 更新主题配色：
    // 如果当前所设置的主题色数小于10，剩余部分获取最后一个主题色的相近颜色作为配色
    const updateTheme = () => {
      if (!chartRef.value) return;

      for (let i = 0; i < 10; i++) {
        chartRef.value.style.setProperty(
          `--theme-color-${i + 1}`,
          themeColors.value[i]
        );
      }

      let colorList = [];
      charts.theme({
        styleSheet: {
          paletteQualitative10: themeColors.value,
        },
      });
      // slidesStore.updateElement({ id: handleElementId.value, props })
      addHistorySnapshot();
    };
    watch(
      () => handleElement.value,
      (val: any) => {
        if (val == null) return;
        if (
          val.chartType != "2dmap" &&
          val.themeColor &&
          val.themeColor.length > 1
        ) {
          charts.theme({
            styleSheet: {
              paletteQualitative10: val.themeColor,
            },
          });
        }
      },
      { immediate: false }
    );
    watch(themeColors, (val, oldval) => {
      if (val.toString() != oldval.toString()) updateTheme();
    });
    // onMounted(updateTheme)

    // 更新网格颜色，包括坐标的文字部分
    const updateGridColor = () => {
      if (!chartRef.value) return;
      if (props.gridColor)
        chartRef.value.style.setProperty(`--grid-color`, props.gridColor);
    };

    watch(() => props.gridColor, updateGridColor);
    // onMounted(updateGridColor)

    return {
      chartHeight,
      themeColors,
      slideScale,
      chartRef,
      legend,
      filter,
    };
  },
});
</script>

<style lang="scss" scoped>
.chart {
  display: flex;
}

.chart-content {
  transform-origin: 0 0;
}
</style>

<style lang="scss">
.chart-content {
  $ct-series-names: (a, b, c, d, e, f, g, h, i, j);

  --theme-color-1: #666;
  --theme-color-2: #666;
  --theme-color-3: #666;
  --theme-color-4: #666;
  --theme-color-5: #666;
  --theme-color-6: #666;
  --theme-color-7: #666;
  --theme-color-8: #666;
  --theme-color-9: #666;
  --theme-color-10: #666;

  @for $i from 1 to length($ct-series-names) {
    $color: var(--theme-color-#{$i});

    .ct-series-#{nth($ct-series-names, $i)} .ct-line {
      stroke: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-point {
      stroke: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-area {
      fill: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-bar {
      stroke: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-slice-pie {
      fill: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-slice-donut {
      stroke: $color;
    }
  }

  --grid-color: rgba(0, 0, 0, 0.4);

  .ct-grid {
    stroke: var(--grid-color);
  }

  .ct-label {
    fill: var(--grid-color);
    color: var(--grid-color);
  }
}

.legends {
  height: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 14px;
}

.legend {
  display: flex;
  align-items: center;

  & + .legend {
    margin-left: 10px;
  }

  .block {
    width: 10px;
    height: 10px;
    margin-right: 5px;
  }
}
</style>
